﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace BenevolentSunData
{
    public class MirrorCell : Cell
    {

        public override string Name
        {
            get
            {
                return "Mirror";
            }
        }

        public override string Note
        {
            get
            {
                if (GetBeam(Direction.North) != null ||
                    GetBeam(Direction.South) != null)
                {
                    return "Toggle rotation to change beam reflection direction.";
                }
                return "Hit with the beam to reflect the beam in a different direction";
            }
        }


        #region State
        private uint reflectPosition = 0;
        [ContentSerializer(Optional=true)]
        public uint ReflectPosition
        {
            get { return reflectPosition; }
            set {
                reflectPosition = value;
                if (reflectPosition > 1)
                    reflectPosition = 0;
                Rotation = (float)(Math.PI / 2.0f) * reflectPosition;
            }
        }
        #endregion


        #region Graphics
        [ContentSerializerIgnore]
        public Model Model;

        [ContentSerializerIgnore]
        public Material Material = new Material();

        Matrix[] boneTransforms;
        #endregion


        #region Initialization
        public MirrorCell()
        {
        }

        public override void LoadContent(ContentManager Content, Map map)
        {
            Material = map.Skin.GetMaterial("Mirror");
            Model = Content.Load<Model>("Models/Mirror");
            boneTransforms = new Matrix[Model.Bones.Count];
            Model.CopyAbsoluteBoneTransformsTo(boneTransforms);

            base.LoadContent(Content, map);
        }
        #endregion


        #region Beams
        public override List<Direction> AddInput(Beam beam, Direction direction)
        {
            MergeBeam(beam, direction);

            List<Direction> output = new List<Direction>();

            Direction reflection = Reflect(direction);
            if (MergeBeam(beam, reflection))
                output.Add(reflection);
            
            return output;
        }

        public Direction Reflect(Direction incoming)
        {
            if (reflectPosition == 0)
            {
                switch (incoming)
                {
                    case Direction.North:
                        return Direction.East;
                    case Direction.South:
                        return Direction.West;
                    case Direction.East:
                        return Direction.North;
                    case Direction.West:
                        return Direction.South;
                    default:
                        throw (new Exception("Unknown direction: " + incoming));
                }
            }
            else
            {
                switch (incoming)
                {
                    case Direction.North:
                        return Direction.West;
                    case Direction.South:
                        return Direction.East;
                    case Direction.East:
                        return Direction.South;
                    case Direction.West:
                        return Direction.North;
                    default:
                        throw (new Exception("Unknown direction: " + incoming));
                }
            }
        }
        #endregion


        #region Interactions
        public override bool Interact()
        {
            ReflectPosition++;
            
            return true;
        }
        #endregion


        #region Drawing
        public override void Draw(Vector3 position)
        {
            foreach (ModelMesh mesh in Model.Meshes)
            {
                Matrix world =
                    boneTransforms[mesh.ParentBone.Index] *
                    Matrix.CreateFromYawPitchRoll(Rotation, 0f, 0f) *
                    Matrix.CreateTranslation(position);
                Material.DrawMesh(mesh, world, Map.PointLights, Map.BeamLights);
            }
        }
        #endregion


        #region ICloneable
        public override object Clone()
        {
            MirrorCell cell = new MirrorCell();
            cell.Coords = new Point(Coords.X, Coords.Y);
            cell.ReflectPosition = reflectPosition;
            cell.Model = Model;
            cell.Material = Material.Clone();
            cell.boneTransforms = boneTransforms;
            cell.floorBoneTransforms = floorBoneTransforms;
            cell.floorModel = floorModel;
            cell.floorMaterial = floorMaterial.Clone();
            return cell;
        }
        #endregion

    }
}
